#include "config.h"

#include "ms2lstat_mod.h"

#define EMPTY(tok)	(*tok == '-' && tok[1] == '\0')

static ECMBOOL
ns41_parse(char *line, lent_t *lent)
{
	char	*tok, *p;
	char	datetime_str[1024];
	ecm_uint32	n;
	ecm_uint32	duration;
	ecm_uint32	status;
	ecm_uint64	file_length;
	ecm_uint64	file_size;
	ecm_uint64	c_bytes;
	ECMBOOL		stream_mode = ECM_TRUE;

	if (*line == '#')
		return ECM_FALSE;

	if ((tok = ecm_strtok(line, " ", &p)) == NULL) {
		lp_error("cannot find c-ip field");
		return ECM_FALSE;
	}

	/* date */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find date field");
		return ECM_FALSE;
	}
	n = ecm_snprintf(datetime_str, 1024, "%s ", tok);

	/* time */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find time field");
		return ECM_FALSE;
	}

	ecm_snprintf(datetime_str + n, 1024 - n, "%s", tok);

	lent->tick = lp_get_timetick(datetime_str);
	if (lent->tick == 0) {
		lp_error("invalid date time");
		return ECM_FALSE;
	}

	/* c-dns */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-dns field");
		return ECM_FALSE;
	}

	/* c-uri-stem */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-uri-stem field");
		return ECM_FALSE;
	}

	lent->mid = lp_get_mid(tok);

	/* c-starttime */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-starttime field");
		return ECM_FALSE;
	}
	if (EMPTY(tok)) {
		lent->startstamp = 0;
	}
	else if (ecm_sscanf(tok, "%u", &lent->startstamp) != 1) {
		lp_error("invalid c-starttime");
		return ECM_FALSE;
	}

	/* x-duration */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find x-duration field");
		return ECM_FALSE;
	}

	if (ecm_sscanf(tok, "%u", &duration) != 1) {
		lp_error("%s: x-duration format error", tok);
		return ECM_FALSE;
	}

	/* c-rate */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-rate field");
		return ECM_FALSE;
	}
	if (ecm_sscanf(tok, "%d", &lent->playback_rate) != 1) {
		lp_error("%s: invalid c-rate value", tok);
		return ECM_FALSE;
	}

	/* c-status */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-status field");
		return ECM_FALSE;
	}
	if (ecm_sscanf(tok, "%u", &status) != 1) {
		lp_error("%s: invalid c-status value", tok);
		return ECM_FALSE;
	}
	if (status < 100 || status >= 600) {
		lp_error("%u: invalid c-status value", status);
		return ECM_FALSE;
	}
	lent->status = status;

	/* c-playerid */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-playerid field");
		return ECM_FALSE;
	}

	lent->cid = lp_get_cid(tok);

	/* c-playerversion */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-playerversion field");
		return ECM_FALSE;
	}

	/* c-playerlanguage */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-playerlanguage field");
		return ECM_FALSE;
	}

	/* cs(User-Agent) */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find cs(User-Agent) field");
		return ECM_FALSE;
	}

	/* cs(Referer) */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find cs(Referer) field");
		return ECM_FALSE;
	}

	/* c-hostexe */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-hostexe field");
		return ECM_FALSE;
	}

	/* c-hostexecver */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-hostexecver field");
		return ECM_FALSE;
	}

	/* c-os */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-os field");
		return ECM_FALSE;
	}

	/* c-osversion */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-osversion field");
		return ECM_FALSE;
	}

	/* c-cpu */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-cpu field");
		return ECM_FALSE;
	}

	/* filelength */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find filelength field");
		return ECM_FALSE;
	}
	if (EMPTY(tok)) {
		file_length = 0;
	}
	else if (ecm_sscanf(tok, "%I64u", &file_length) != 1) {
		lp_error("%s: invalid file length", tok);
		return ECM_FALSE;
	}

	/* filesize */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find filesize field");
		return ECM_FALSE;
	}
	if (EMPTY(tok)) {
		file_size = 0;
	}
	else if (ecm_sscanf(tok, "%I64u", &file_size) != 1) {
		lp_error("%s: invalid file size", tok);
		return ECM_FALSE;
	}

	/* avgbandwidth */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find avgbandwidth");
		return ECM_FALSE;
	}

	/* protocol */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find protocol");
		return ECM_FALSE;
	}

	/* transport */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find transport");
		return ECM_FALSE;
	}

	/* audiocodec */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find audiocodec");
		return ECM_FALSE;
	}
	if (ecm_strcmp(tok, "-") != 0)
		stream_mode = ECM_FALSE;
	/* videocodec */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find videocodec");
		return ECM_FALSE;
	}
	if (stream_mode && ecm_strcmp(tok, "-") != 0)
		stream_mode = ECM_FALSE;

	/* channelURL */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find channelURL");
		return ECM_FALSE;
	}

	/* sc-bytes */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find sc-bytes");
		return ECM_FALSE;
	}

	/* c-bytes */
	if ((tok = ecm_strtok(NULL, " ", &p)) == NULL) {
		lp_error("cannot find c-bytes");
		return ECM_FALSE;
	}

	if (ecm_sscanf(tok, "%I64u", &c_bytes) != 1) {
		lp_error("%s: invalid c-bytes", tok);
		return ECM_FALSE;
	}

	lent->duration = duration;
	if (lent->playback_rate == 1) {
		if (lent->tick > lent->duration)
			lent->tick -= lent->duration;
	}
	else if (lent->playback_rate == 5 || lent->playback_rate == -5) {
		lent->tick -= (lent->duration / 5);
	}

	if (c_bytes == 0) {
		lent->duration = 0;
	}

	if (status == 200 && file_size > 0 && file_length > 0)
		lp_update_media_info(lent->mid, file_length, file_size);

	return ECM_TRUE;
}

lparser_op_t	lparser_op = {
	ns41_parse,
};
